package kr.pe.johnkim.pushchat.mobile.service;

import kr.pe.johnkim.pushchat.mobile.dao.PushChatMessageDao;
import kr.pe.johnkim.pushchat.mobile.dao.PushChatRecognitionDao;
import kr.pe.johnkim.pushchat.mobile.dao.PushChatUserDao;
import kr.pe.johnkim.pushchat.mobile.domain.PushChatMessage;
import kr.pe.johnkim.pushchat.mobile.domain.PushChatRecognition;
import kr.pe.johnkim.pushchat.mobile.domain.PushChatUser;
import kr.pe.johnkim.pushchat.mobile.util.PushChatCommon;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.List;

/**
 * @author : John_Kim <cale9797@gmail.com>
 * @date : 13. 6. 12.
 */
@Service
public class PushChatMessageServiceImpl implements PushChatMessageService {

    // SLF4J Logging
    private Logger logger = LoggerFactory.getLogger(PushChatMessageServiceImpl.class);

    @Autowired
    private PushChatMessageDao pushChatMessageDao;

    @Autowired
    private PushChatRecognitionDao pushChatRecognitionDao;

    @Autowired
    private PushChatUserDao pushChatUserDao;

    @Autowired
    private PushChatCommon pushChatCommon;

    // 생성 할 메시지 썸메일 가로 크기.
    private @Value("${message.thumbnail.width}") int messageThumbnailWidth;

    // 생성 할 메시지 썸네일 세로 크기.
    private @Value("${message.thumbnail.height}") int messageThumbnailHeight;

    /**
     * 채팅방에 메시지를 추가 한다.
     *
     * @param pushChatMessage
     */
    @Override
    public void registerMessage(PushChatMessage pushChatMessage) {
        logger.info("registerMessage");

        // 채팅방에 메시지를 추가 한다.
        this.pushChatMessageDao.registerMessage(pushChatMessage);

        /*
        채팅방 참여자 목록을 가져 와서 인식 테이블의 읽음 컬럼값을 모두 'N' 으로 업데이트 한다.

        1. 채팅방 참여자 목록을 가져 온다.
        2. 인식 테이블의 읽음 값을 'N' 으로 업데이트 한다.

        인식 테이블에 등록되지 않은 사용자는 읽음여부를 업데이트 할 수 없다.
        채팅방에도 들어오지 않았기 때문에 새롭게 채팅방이 생성되었다는 알림이 먼저이다.
        * */

        PushChatUser parameter = new PushChatUser();

        parameter.setPushChatChatIdChat(pushChatMessage.getPushChatChatIdChat());
        parameter.setPushChatChatOwner(pushChatMessage.getPushChatChatOwner());
        parameter.setActivateYn("Y");

        for(PushChatUser pushChatUser : this.pushChatUserDao.selectUserList(parameter)) {
            PushChatRecognition recognition = new PushChatRecognition();
            recognition.setMemberId(pushChatUser.getMemberId());
            recognition.setReadYn("N");
            recognition.setActivateYn("Y");
            recognition.setModifyDate(this.pushChatCommon.getCurrentDate());
            recognition.setPushChatChatIdChat(pushChatUser.getPushChatChatIdChat());
            recognition.setPushChatChatOwner(pushChatUser.getPushChatChatOwner());

            this.pushChatRecognitionDao.updateReadYn(recognition);
        }
    }

    /**
     * 1. 채팅방에 이미지를 추가 한다.
     * 2. 이미지 추가에 성공하면 메시지를 등록 한다.
     *
     * @param pushChatMessage
     * @param file
     */
    @Override
    public void registerMessageWithImage(PushChatMessage pushChatMessage, String uploadMessageImagePath, String uploadMessageThumbnailPath, MultipartFile file) {
        logger.info("registerMessageWithImage");

        // 이미지 파일명.
        String fileName = file.getOriginalFilename();

        logger.info("> file size : {}", file.getSize());
        logger.info("> file name : {}", file.getOriginalFilename());

        // 이미지를 업로드 한다.
        try {
            InputStream inputStream = file.getInputStream();
            OutputStream outputStream = new FileOutputStream(uploadMessageImagePath + fileName);

            int bytesRead;

            byte[] buffer = new byte[8192];

            while((bytesRead = inputStream.read(buffer, 0, 8192)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }

            outputStream.close();
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 썸네일을 생성 한다.
        try {
            // 썸네일 크기를 설정 한다.
            int width = messageThumbnailWidth;
            int height = messageThumbnailHeight;

            // 원본 이미지 파일을 가져 온다.
            File src = new File(uploadMessageImagePath + fileName);

            BufferedImage bufferedImage = ImageIO.read(src);

            // Aspect Ratio 를 유지하기 위해서 크기를 조정 한다.
            if((float)width/bufferedImage.getWidth() > (float)height/bufferedImage.getHeight()) {
                width = (int)(bufferedImage.getWidth() * ((float)height/bufferedImage.getHeight()));
            } else {
                height = (int)(bufferedImage.getHeight() * ((float)width/bufferedImage.getWidth()));
            }

            BufferedImage thImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

            Graphics2D graphics2D = thImg.createGraphics();
            graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            graphics2D.drawImage(bufferedImage, 0, 0, width, height, null);
            graphics2D.dispose();

            File destinationFile = new File(uploadMessageThumbnailPath + fileName);
            ImageIO.write(thImg, "png", destinationFile);
        } catch (Exception e) {
            e.printStackTrace();
        }

        // 채팅방에 메시지를 추가 한다.
        this.pushChatMessageDao.registerMessage(pushChatMessage);

        /*
        채팅방 참여자 목록을 가져 와서 인식 테이블의 읽음 컬럼값을 모두 'N' 으로 업데이트 한다.

        1. 채팅방 참여자 목록을 가져 온다.
        2. 인식 테이블의 읽음 값을 'N' 으로 업데이트 한다.

        인식 테이블에 등록되지 않은 사용자는 읽음여부를 업데이트 할 수 없다.
        채팅방에도 들어오지 않았기 때문에 새롭게 채팅방이 생성되었다는 알림이 먼저이다.
        * */

        PushChatUser parameter = new PushChatUser();

        parameter.setPushChatChatIdChat(pushChatMessage.getPushChatChatIdChat());
        parameter.setPushChatChatOwner(pushChatMessage.getPushChatChatOwner());
        parameter.setActivateYn("Y");

        for(PushChatUser pushChatUser : this.pushChatUserDao.selectUserList(parameter)) {
            PushChatRecognition recognition = new PushChatRecognition();
            recognition.setMemberId(pushChatUser.getMemberId());
            recognition.setReadYn("N");
            recognition.setActivateYn("Y");
            recognition.setModifyDate(this.pushChatCommon.getCurrentDate());
            recognition.setPushChatChatIdChat(pushChatUser.getPushChatChatIdChat());
            recognition.setPushChatChatOwner(pushChatUser.getPushChatChatOwner());

            this.pushChatRecognitionDao.updateReadYn(recognition);
        }
    }

    /**
     * 채팅 메시지 목록을 가져 온다.
     *
     * @param pushChatMessage
     * @return
     */
    @Override
    public List<PushChatMessage> selectMessageList(PushChatMessage pushChatMessage) {
        logger.info("selectMessageList");
        return this.pushChatMessageDao.selectMessageList(pushChatMessage);
    }

    /**
     * 채팅방의 메시지를 비활성화 한다.
     *
     * @param pushChatMessage
     */
    @Override
    public void updateDeactivateMessage(PushChatMessage pushChatMessage) {
        logger.info("updateDeactivateMessage");
        this.pushChatMessageDao.updateDeactivateMessage(pushChatMessage);
    }
}
